<?php
/**
 * This class provide authorization api for user.
 * + Can be extended to user
 * + For far future support OAUTH2/OAUTH WRAP with permission of doing as user.
 * @package     nuo
 * @subpackage  nuo.user
 * @author      Nam Nguyen <nam.ngvan@gmail.com>
 * @version     1.0
 * @since       Apr 18, 2013
 */

require_once 'nuo/classes/acl/interface.class.php';

class Nuo_Acl_User implements Nuo_Acl_Interface
{

	/**
	 * Storage authorization allow data
	 * @access  protected
	 * @var     array
	 */
	protected $_vars = array();

	/**
	 * current cached role
	 */
	protected $_id = NULL;

	/**
	 * @static
	 * @access    protected
	 * @var       array
	 */
	static private $_instances = array();

	/**
	 * @access  public
	 * @param   int   $id
	 * @return  void
	 */
	private function __construct($id)
	{
		$cacheKey = 'core/permission:' . $id;

		$this -> _vars = Nuo_Cache::instance()-> read($cacheKey);

		if (false == $this -> _vars)
		{
			$this -> _vars = Nuo::getApi('permission') -> loadPermission($id);

			Nuo_Cache::instance()-> write($cacheKey, $this -> _vars);
		}
	}

	/**
	 * Factory user storage data
	 * @static
	 * @param   int   $id
	 * @return  Nuo_Acl_User
	 */
	static public function factory($id)
	{
		if (isset(self::$_instances[$id]))
		{
			return self::$_instances[$id];
		}

		return self::$_instances[$id] = new self($id);
	}

	/**
	 * Get permission id
	 * @access  public
	 * @return  int
	 */
	function getId()
	{
		return $this -> _id;
	}

	/**
	 * Set new permission value associate with action
	 * WARNING:
	 * + Do not store this value to database
	 * + To store new value, use permission api instead
	 * @access  public
	 * @param   string  $action
	 * @param   mixed   $value
	 * @return  Nuo_Permission
	 */
	function setAllow($action, $value)
	{
		$this -> _vars[$action] = $value;
		return $this;
	}

	/**
	 * Get permission of this action
	 * @access public  int
	 * @param  string  $action
	 * @return mixed
	 */
	function allow($action)
	{
		return isset($this -> _vars[$action]) ? $this -> _vars[$action] : false;
	}

	/**
	 * Required user to allow to action.
	 * + If user has authorized to do "action", return true
	 * + If user has no permission to pass "action", redirect user to login required
	 * or permission deined page.
	 * + If you want to get permission instead of required user, please use
	 * ":allow()" instead of this method.
	 * @access  public
	 * @param   string   $action
	 * @return  true
	 */
	function required($action)
	{
		$value = isset($this -> _vars[$action]) ? $this -> _vars[$action] : false;

		if (!$value)
		{
			throw new Exception('Could not pass authorization of ' . $action);
		}
		return true;
	}
}
